#include <iostream>
#include <cstring>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string>
#include <algorithm>
using namespace std;
const int N = 20;
string cmd_line;
char* g_argv[N];    // 用于储存分割后的命令
// shell运行原理： 通过让子进程执行命令，父进程等待&&解析命令
int main()
{
  // 命令行解释器一定是一个常住内存的解释器，不退出
  while(true)
  {
    // 1. 打印出提示信息
    cout<<"[root@localhost myshell]# ";
    fflush(stdout);   // 需要手动刷新缓冲区 
    // 2. 获取用户的键盘输入
    getline(cin, cmd_line);
    // cout<<cmd_line<<endl;
    // 3. 命令字符串解析
    int i=0;    // g_argv[N]的下标 
    while (cmd_line.find(" ") != string::npos)
{
    int found = cmd_line.find(" ");
    string subStr = cmd_line.substr(0, found);
    g_argv[i] = new char[subStr.length() + 1];
    strcpy(g_argv[i++], subStr.c_str());
    cmd_line = cmd_line.substr(found + 1);
    // cout<<cmd_line<<endl;
}
g_argv[i] = new char[cmd_line.length() + 1];
    strcpy(g_argv[i], cmd_line.c_str());
    g_argv[i++] = (char*)cmd_line.c_str();
    g_argv[i++] = NULL;
    //for(int j=0;g_argv[j];++j)
    //{
    //  cout<<g_argv[j]<<endl;
    //}
    // 4.内置命令，让父进程（shell)自己执行的命令，叫做内置命令或者内建命令
    if(strcmp(g_argv[0], "cd") == 0)
{
  if(g_argv[1] != NULL) chdir(g_argv[1]);
}
    
    // 5.fork()
    pid_t id = fork();
  cout<<g_argv[0]<<endl;
    if(id == 0)
    {
      // child
      cout<<"下面的功能是子进程执行的" << endl;
      // 当执行cd命令(cd ..)时，只会影响子进程的当前目录，不会影响父进程的路径，所以有第四步
      execvp(g_argv[0], g_argv);
      exit(66);
    }
    // father
    int status = 0;
    pid_t ret = waitpid(id, &status, 0);
    if(ret > 0)
      cout<<"退出码："<<WEXITSTATUS(status)<<endl;
  }
  return 0;
}
